package com.wfit.file.service.impl;

import com.wfit.file.config.MinioConfig;
import com.wfit.file.config.MinioConfigProperties;
import com.wfit.file.service.FileStorageService;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
@EnableConfigurationProperties(MinioConfigProperties.class)
@Import(MinioConfig.class)
public class MinIOFileStorageService implements FileStorageService {
    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfigProperties minioConfigProperties;

    private final static String separator = "/";

    /**
     * 文件路径
     * @param dirPath
     * @param filename
     * @return
     */
    private String builderFilePath(String dirPath,String filename) {
        StringBuilder stringBuilder = new StringBuilder(50);
        if (!StringUtils.isEmpty(dirPath)) {
            stringBuilder.append(dirPath).append(separator);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
        String todayStr = simpleDateFormat.format(new Date());
        stringBuilder.append(todayStr).append(separator);
        stringBuilder.append(filename);
        return stringBuilder.toString();

    }

    /**
     * 图片上传
     * @param prefix //文件前缀
     * @param filename  文件名
     * @param inputStream 文件流
     * @return  文件全路径
     */
    public String uploadImgFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs
                    .builder()
                    .object(filePath)
                    .contentType("image/jpg")
                    .bucket(minioConfigProperties.getBucket())
                    .stream(inputStream, inputStream.available(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder stringBuilder = new StringBuilder(minioConfigProperties.getReadPath());
            stringBuilder.append(separator + minioConfigProperties.getBucket());
            stringBuilder.append(separator).append(filePath);
            return stringBuilder.toString();
        } catch (Exception e) {
            log.error("minio put file error.",e);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * html文件上传
     * @param prefix  文件前缀
     * @param filename   文件名
     * @param inputStream  文件流
     * @return
     */
    public String uploadHtmlFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs
                    .builder()
                    .object(filePath)
                    .contentType("text/html")
                    .bucket(minioConfigProperties.getBucket())
                    .stream(inputStream, inputStream.available(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder stringBuilder = new StringBuilder(minioConfigProperties.getReadPath());
            stringBuilder.append(separator + minioConfigProperties.getBucket());
            stringBuilder.append(separator).append(filePath);
            return stringBuilder.toString();
        } catch (Exception e) {
            log.error("minio put file error.",e);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 删除文件
     * @param pathUrl  文件全路径
     */
    public void delete(String pathUrl) {
        // 去掉域名
        String key = pathUrl.replace(minioConfigProperties.getEndpoint() + "/", "");
        // 指定 substring 的第一个匹配项的索引，如果没有此类匹配项，则为 -1
        int index = key.indexOf(separator);
        // 截取bucket
        String bucket = key.substring(0, index);
        String filePath = key.substring(index + 1);
        // 删除objects
        RemoveObjectArgs build = RemoveObjectArgs
                .builder()
                .bucket(bucket)
                .object(filePath)
                .build();
        try {
            minioClient.removeObject(build);
        } catch (Exception e) {
            log.error("minio remove file error.  pathUrl:{}",pathUrl);
            e.printStackTrace();
        }
    }

    /**
     * 文件下載
     * @param pathUrl  文件全路径
     * @return
     */
    public byte[] downLoadFile(String pathUrl) {
        String key = pathUrl.replace(minioConfigProperties.getEndpoint() + "/", "");
        int index = key.indexOf("/");
        String bucket = key.substring(0, index);
        String filePath = key.substring(index + 1);
        InputStream inputStream = null;
        try {
            inputStream = minioClient.getObject(GetObjectArgs
                    .builder()
                    .bucket(bucket)
                    .object(filePath)
                    .build());
        } catch (Exception e) {
            log.error("minio down file error.  pathUrl:{}",pathUrl);
            // 这行代码的作用是打印当前异常的堆栈跟踪信息，帮助开发者定位和调试问题。
            e.printStackTrace();
        }
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while (true) {
            try {
                if (!((rc = inputStream.read(buff,0,100)) > 0)) break;
            } catch (IOException e) {
                e.printStackTrace();
            }
            byteArrayOutputStream.write(buff,0,rc);
        }

        return byteArrayOutputStream.toByteArray();
    }
}
